"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = require("../../config");
const ticket_1 = require("../../utils/ticket");
function buildViewLines(lineGroups, selections) {
    return lineGroups.map((line, index) => {
        const id = `line-${index}`;
        return {
            id,
            selected: !!selections[id],
            segments: line.map((segment) => {
                if (segment.type === 'text') {
                    return {
                        type: 'text',
                        id: segment.id,
                        raw: segment.raw,
                    };
                }
                return {
                    type: 'number',
                    id: segment.id,
                    display: (0, ticket_1.formatNumberToken)(segment),
                    state: segment.state,
                };
            }),
        };
    });
}
function getDecimalPlaces(value) {
    const trimmed = value.trim();
    if (!trimmed.includes('.')) {
        return 0;
    }
    const [, decimals = ''] = trimmed.split('.');
    return decimals.length;
}
function applyDeltaToTokens(tokens, delta, mode, target, deltaPrecision, allowDecimal) {
    const direction = mode === 'plus' ? 1 : -1;
    let affected = 0;
    tokens.forEach((token) => {
        if (token.type !== 'number') {
            return;
        }
        if (target === 'yellow' && token.state !== 'yellow') {
            return;
        }
        if (target === 'red' && token.state !== 'red') {
            return;
        }
        const precision = allowDecimal ? Math.max(token.precision, deltaPrecision) : 0;
        const factor = Math.pow(10, precision);
        const currentScaled = Math.round(token.value * factor);
        const deltaScaled = Math.round(delta * factor);
        const signedScaled = currentScaled + direction * deltaScaled;
        token.value = allowDecimal ? signedScaled / factor : Math.round(signedScaled);
        token.precision = precision;
        affected += 1;
    });
    return affected;
}
const pageState = {
    rawText: '',
    tokens: [],
    baselineTokens: [],
    lineGroups: [],
    lineRects: [],
    dragSelecting: false,
    dragMode: null,
    lastDragLineId: null,
};
function updateModifyTarget(page, target) {
    const label = target === 'yellow' ? '仅修改黄色（点此切换）' : '仅修改红色（点此切换）';
    page.setData({ modifyTarget: target, modifyTargetLabel: label });
}
function updateLineRects(page) {
    wx.nextTick(() => {
        page
            .createSelectorQuery()
            .selectAll('.line-row')
            .boundingClientRect((rects) => {
            if (!Array.isArray(rects)) {
                pageState.lineRects = [];
                return;
            }
            const typedRects = rects;
            pageState.lineRects = typedRects.map((rect, index) => ({
                id: `line-${index}`,
                top: rect.top,
                bottom: rect.bottom,
            }));
        })
            .exec();
    });
}
function refreshLines(page, preserveSelections = true) {
    const grouped = (0, ticket_1.tokensToLines)(pageState.tokens);
    pageState.lineGroups = grouped;
    const previousSelections = preserveSelections ? page.data.lineSelections || {} : {};
    const selections = {};
    grouped.forEach((_, index) => {
        const id = `line-${index}`;
        selections[id] = !!previousSelections[id];
    });
    const hasSelection = Object.values(selections).some(Boolean);
    page.setData({
        lines: buildViewLines(grouped, selections),
        lineSelections: selections,
        hasSelection,
    });
    updateLineRects(page);
}
function setLineSelection(page, lineId, selected) {
    if (!lineId || !pageState.lineGroups.length) {
        return;
    }
    const currentSelections = { ...(page.data.lineSelections || {}) };
    if (currentSelections[lineId] === selected) {
        return;
    }
    currentSelections[lineId] = selected;
    const hasSelection = Object.values(currentSelections).some(Boolean);
    page.setData({
        lineSelections: currentSelections,
        hasSelection,
        lines: buildViewLines(pageState.lineGroups, currentSelections),
    });
}
function serializeSelectedLineGroups(lineGroups, selectedIds) {
    if (!selectedIds.length) {
        return '';
    }
    const lines = selectedIds
        .map((id) => Number(id.replace('line-', '')))
        .filter((index) => !Number.isNaN(index))
        .map((index) => lineGroups[index] || [])
        .map((line) => line
        .map((segment) => segment.type === 'number'
        ? (0, ticket_1.formatNumberToken)(segment)
        : segment.raw)
        .join(''));
    return lines.join('\n');
}
function findLineIdByClientY(clientY) {
    const hit = pageState.lineRects.find((rect) => clientY >= rect.top && clientY <= rect.bottom);
    return hit ? hit.id : null;
}
function reparseTokens(page, allowDecimal) {
    const tokens = (0, ticket_1.parseTicketText)(pageState.rawText, { allowDecimal });
    (0, ticket_1.markPriceTokens)(tokens);
    pageState.tokens = tokens;
    pageState.baselineTokens = (0, ticket_1.cloneTokens)(tokens);
    page.setData({ allowDecimal });
    updateModifyTarget(page, 'yellow');
    refreshLines(page, false);
}
function initialize(page, payload) {
    pageState.rawText = payload.rawText || '';
    const allowDecimal = typeof payload.allowDecimal === 'boolean' ? payload.allowDecimal : config_1.DEFAULT_ALLOW_DECIMAL;
    reparseTokens(page, allowDecimal);
    page.setData({ allowDecimal });
}
Page({
    data: {
        lines: [],
        mode: 'plus',
        delta: '50',
        allowDecimal: config_1.DEFAULT_ALLOW_DECIMAL,
        modifyTarget: 'yellow',
        modifyTargetLabel: '仅修改黄色（点此切换）',
        lineSelections: {},
        hasSelection: false,
        adUnitId: config_1.AD_UNIT_ID_RESULT,
        adError: false,
        showDeltaPicker: false,
        presetDeltas: [50, 100, 200, 300, 400, 500, 1000],
        showCustomInput: false,
        customDeltaInput: '',
    },
    onLoad() {
        const eventChannel = this.getOpenerEventChannel
            ? this.getOpenerEventChannel()
            : undefined;
        if (eventChannel) {
            eventChannel.on('loadData', (payload) => {
                initialize(this, payload);
            });
        }
    },
    onCheckboxTouchStart(event) {
        const lineId = event.currentTarget.dataset.id;
        if (!lineId) {
            return;
        }
        const currentSelections = this.data.lineSelections || {};
        const isSelected = !!currentSelections[lineId];
        pageState.dragSelecting = true;
        pageState.dragMode = isSelected ? 'deselect' : 'select';
        setLineSelection(this, lineId, pageState.dragMode === 'select');
        pageState.lastDragLineId = lineId;
    },
    onCheckboxTouchMove(event) {
        if (!pageState.dragSelecting) {
            return;
        }
        const touch = event.touches && event.touches[0];
        if (!touch) {
            return;
        }
        const lineId = findLineIdByClientY(touch.clientY);
        if (!lineId || lineId === pageState.lastDragLineId) {
            return;
        }
        setLineSelection(this, lineId, pageState.dragMode === 'select');
        pageState.lastDragLineId = lineId;
    },
    onCheckboxTouchEnd() {
        pageState.dragSelecting = false;
        pageState.dragMode = null;
        pageState.lastDragLineId = null;
        updateLineRects(this);
    },
    onToggleState(event) {
        const id = event.currentTarget.dataset.id;
        if (!id) {
            return;
        }
        const target = pageState.tokens.find((token) => token.type === 'number' && token.id === id);
        if (!target) {
            return;
        }
        target.state = (0, ticket_1.cycleState)(target.state);
        refreshLines(this);
    },
    onToggleMode() {
        this.setData({ mode: this.data.mode === 'plus' ? 'minus' : 'plus' });
    },
    onDeltaInput(e) {
        this.setData({ delta: e.detail.value });
    },
    onOpenDeltaPicker() {
        this.setData({ showDeltaPicker: true, showCustomInput: false, customDeltaInput: '' });
    },
    onCloseDeltaPicker() {
        this.setData({ showDeltaPicker: false, showCustomInput: false, customDeltaInput: '' });
    },
    onPickPreset(e) {
        const value = String(e.currentTarget.dataset.value || '');
        if (!value)
            return;
        this.setData({ delta: value, showDeltaPicker: false, showCustomInput: false, customDeltaInput: '' });
    },
    onShowCustomInput() {
        this.setData({ showCustomInput: true, customDeltaInput: '' });
    },
    onCustomDeltaInput(e) {
        this.setData({ customDeltaInput: e.detail.value });
    },
    onConfirmCustomDelta() {
        const v = (this.data.customDeltaInput || '').trim();
        if (!v) {
            wx.showToast({ title: '请输入数值', icon: 'none' });
            return;
        }
        if (Number.isNaN(Number(v))) {
            wx.showToast({ title: '格式不正确', icon: 'none' });
            return;
        }
        this.setData({ delta: v, showDeltaPicker: false, showCustomInput: false, customDeltaInput: '' });
    },
    onApply() {
        const deltaStr = this.data.delta.trim();
        if (!deltaStr) {
            wx.showToast({ title: '请输入调整数值', icon: 'none' });
            return;
        }
        const deltaValue = Number(deltaStr);
        if (Number.isNaN(deltaValue)) {
            wx.showToast({ title: '调整数值格式不正确', icon: 'none' });
            return;
        }
        if (!this.data.allowDecimal && !Number.isInteger(deltaValue)) {
            wx.showToast({ title: '当前模式不支持小数', icon: 'none' });
            return;
        }
        const deltaPrecision = this.data.allowDecimal ? getDecimalPlaces(deltaStr) : 0;
        const affected = applyDeltaToTokens(pageState.tokens, deltaValue, this.data.mode, 'yellow', deltaPrecision, this.data.allowDecimal);
        if (affected === 0) {
            wx.showToast({ title: '未找到可调整的数字', icon: 'none' });
            return;
        }
        refreshLines(this);
    },
    onApplyToRed() {
        ;
        this.applyForTarget('red');
    },
    onApplyToYellow() {
        ;
        this.applyForTarget('yellow');
    },
    applyForTarget(target) {
        const deltaStr = this.data.delta.trim();
        if (!deltaStr) {
            wx.showToast({ title: '请选择或输入数值', icon: 'none' });
            return;
        }
        const deltaValue = Number(deltaStr);
        if (Number.isNaN(deltaValue)) {
            wx.showToast({ title: '调整数值格式不正确', icon: 'none' });
            return;
        }
        const deltaPrecision = this.data.allowDecimal ? getDecimalPlaces(deltaStr) : 0;
        const affected = applyDeltaToTokens(pageState.tokens, deltaValue, this.data.mode, target, deltaPrecision, this.data.allowDecimal);
        if (affected === 0) {
            wx.showToast({ title: '未找到可调整的数字', icon: 'none' });
            return;
        }
        refreshLines(this);
    },
    onClearHighlights() {
        pageState.tokens.forEach((token) => {
            if (token.type === 'number') {
                token.state = 'none';
            }
        });
        updateModifyTarget(this, 'yellow');
        refreshLines(this);
    },
    onDeleteSelectedLines() {
        const selections = this.data.lineSelections || {};
        const selectedIds = Object.keys(selections).filter((id) => selections[id]);
        if (!selectedIds.length) {
            wx.showToast({ title: '请先勾选要删除的行', icon: 'none' });
            return;
        }
        const selectedIndexes = new Set(selectedIds
            .map((id) => Number(id.replace('line-', '')))
            .filter((n) => !Number.isNaN(n)));
        // 依据行索引过滤 Token（按 linebreak 分行）
        const newTokens = [];
        let currentLine = 0;
        pageState.tokens.forEach((t) => {
            if (!selectedIndexes.has(currentLine)) {
                if (t.type !== 'linebreak') {
                    newTokens.push({ ...t });
                }
                else {
                    // 仅在未删除且当前行不是最后可见行时保留换行
                    newTokens.push({ ...t });
                }
            }
            if (t.type === 'linebreak') {
                currentLine += 1;
            }
        });
        // 规范化：如果末尾有多余换行，可保留一次；刷新视图会重新分行
        pageState.tokens = newTokens;
        // 清空选择
        this.setData({ lineSelections: {}, hasSelection: false });
        refreshLines(this, false);
    },
    onCycleModifyTarget() {
        const next = this.data.modifyTarget === 'yellow' ? 'red' : 'yellow';
        updateModifyTarget(this, next);
    },
    onCopyResult() {
        if (!pageState.tokens.length) {
            wx.showToast({ title: '无可复制内容', icon: 'none' });
            return;
        }
        const selections = this.data.lineSelections || {};
        const selectedIds = Object.keys(selections).filter((id) => selections[id]);
        const text = selectedIds.length
            ? serializeSelectedLineGroups(pageState.lineGroups, selectedIds)
            : (0, ticket_1.serializeTokens)(pageState.tokens);
        if (!text) {
            wx.showToast({ title: '选中行暂无内容', icon: 'none' });
            return;
        }
        wx.setClipboardData({ data: text });
    },
    onClearSelections() {
        const selections = {};
        if (pageState.lineGroups.length) {
            pageState.lineGroups.forEach((_, index) => {
                selections[`line-${index}`] = false;
            });
        }
        this.setData({
            lineSelections: selections,
            hasSelection: false,
            lines: buildViewLines(pageState.lineGroups, selections),
        });
    },
    onReset() {
        pageState.tokens = (0, ticket_1.cloneTokens)(pageState.baselineTokens);
        updateModifyTarget(this, 'yellow');
        refreshLines(this);
    },
    onAdError() {
        this.setData({ adError: true });
    },
});
